#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import cgi
import StringIO
import logging
import re
import sys
import traceback
import urlparse
import options
import sys
import models
from google.appengine.ext.webapp import *

class WSGIApplication2(WSGIApplication):
    """
    Modifyed to add new methods __before__ and __after__
    before the get/post/delete/etc methods and then 
    AFTER RESPONSE.  This is important because it means you 
    can do work after the response has been returned to the browser
    """
    def __init__(self, url_mapping, debug=False):
        """Initializes this application with the given URL mapping.

        Args:
            url_mapping: list of (URI, RequestHandler) pairs (e.g., [('/', ReqHan)])
            debug: if true, we send Python stack traces to the browser on errors
        """
        self._init_url_mappings(url_mapping)
        self.__debug = debug
        plugs = models.Code.all().order('order').fetch(100);
        urls={}
        if plugs != []: # new month
            for code in plugs:
                if code.active:
                    compiled_code = compile(code.data, '<string>', 'exec')
                    exec(compiled_code, globals())
                    urls.update(getplugurl())
#        urls={1:('r',re.compile('/admin'),blog.MainPage),0:('i',re.compile('/'),blog.AdminList)}
        for num,url in urls.items():
            if (url[0]=='r'):
                self._url_mapping[num]=url[1:]
            elif (url[0]=='i'):
                self._url_mapping.insert(num,url[1:])
            elif (url[0]=='d'):
                del self._url_mapping[num]
                
        WSGIApplication.active_instance = self
        self.current_request_args = ()
        self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
  
    def __call__(self, environ, start_response):
        import options
        # Check that middleware is still uninitialised.
        
        self.load_middleware()
        """Called by WSGI when a request comes in."""
        request = Request(environ)
        response = Response()
        
        for middleware_method in self._request_middleware:
            response = middleware_method(request)
            if response:
                return response

        WSGIApplication.active_instance = self

        handler = None
        groups = ()
        for regexp, handler_class in self._url_mapping:
            match = regexp.match(request.path)
            if match:
                handler = handler_class()
                handler.initialize(request, response)
                groups = match.groups()
                break

        self.current_request_args = groups 
            
        if handler:
            try:
                for middleware_method in self._view_middleware:
                    response = middleware_method(request,*groups)
                    if response:
                        return response
                method = environ['REQUEST_METHOD']
                if method == 'GET':
                    handler.get(*groups)
                elif method == 'POST':
                    handler.post(*groups)
                elif method == 'HEAD':
                    handler.head(*groups)
                elif method == 'OPTIONS':
                    handler.options(*groups)
                elif method == 'PUT':
                    handler.put(*groups)
                elif method == 'DELETE':
                    handler.delete(*groups)
                elif method == 'TRACE':
                    handler.trace(*groups)
                else:
                    handler.error(501)
                response.wsgi_write(start_response)
                for middleware_method in self._response_middleware:
                        response = middleware_method(request, response)
            except Exception, e:
                if e==None:
                    e="exception!!!"
                for middleware_method in self._exception_middleware:
                    response = middleware_method(request, e)
                    if response:
                        return response
                handler.handle_exception(e, self.__debug)
        else:
            response.set_status(404)
            response.wsgi_write(start_response)
        return ['']
    def load_middleware(self):
        """
        Populate middleware lists from settings.MIDDLEWARE_CLASSES.

        Must be called after the environment is fixed (see __call__).
        """
        self._view_middleware = []
        self._response_middleware = []
        self._exception_middleware = []
        self._request_middleware = []
        for middleware_path in options.MIDDLEWARE_CLASSES:
            try:
                dot = middleware_path.rindex('.')
            except Exception, e:
                raise Exception
            mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
            try:
                mod = __import__(mw_module, {}, {}, [''])
            except Exception, e:
                raise Exception
            try:
                mw_class = getattr(mod, mw_classname)
            except Exception, e:
                raise Exception

            try:
                mw_instance = mw_class()
            except Exception, e:
                continue

            if hasattr(mw_instance, 'process_request'):
                self._request_middleware.append(mw_instance.process_request)
            if hasattr(mw_instance, 'process_view'):
                self._view_middleware.append(mw_instance.process_view)
            if hasattr(mw_instance, 'process_response'):
                self._response_middleware.insert(0, mw_instance.process_response)
            if hasattr(mw_instance, 'process_exception'):
                self._exception_middleware.insert(0, mw_instance.process_exception)